package edu.tfh.s2.ehkbot.gerete.sensoren;

import edu.tfh.s2.ehkbot.daten.GeraeteRegistration;
import edu.tfh.s2.ehkbot.steuerung.BusAdresse;
import edu.tfh.s2.ehkbot.steuerung.BusAdressierbar;
import edu.tfh.s2.ehkbot.util.Subject;

/**
 * Sensor implementiert die Schnittstelle für ein Sensor. Sensor nutzt das State Pattern um zwischen
 * Simulation und Real verschieden Verhalten zu Implementieren. Sensor nutzt das Observer Pattern um seinen
 * Messwert an Beobachter zu verteilen.
 * 
 * @author s2zehn
 */
public class Sensor extends Subject implements BusAdressierbar {
	/**
	 * Implementiert das State für Sensor.
	 */
	public interface SensorState {
		/**
		 * Liefert den rohen Messwert.
		 * 
		 * @return den rohnen Messwert.
		 */
		public double getMessertRoh();

		/**
		 * Testet ob der Sensor funktioniert.
		 * 
		 * @return true wenn der Sensor funktioniert.
		 */
		public boolean testeFunktion();
	}

	/**
	 * Die BusAdresse
	 */
	private BusAdresse busAdresse;

	/**
	 * Der rohe Messwert um offset erhört.
	 */
	private double offset = 0;

	private SensorState state;

	/**
	 * Der rohe Messwert wird mit steigung mutipliziert.
	 */
	private double steigung = 1;

	/**
	 * Konstruktor für Sensor
	 * 
	 * @param busAdresse
	 *            Die BusAdresse.
	 * @param state
	 *            Das State welches das Verhalten bestimmt.
	 */
	public Sensor(BusAdresse busAdresse, SensorState state) {
		this.busAdresse = busAdresse;
		this.state = state;
		GeraeteRegistration.getInstance().register(this);
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!(obj instanceof Sensor))
			return false;

		Sensor rhs = (Sensor) obj;
		return this.getBusAdresse().equals(rhs.getBusAdresse());
	}

	/**
	 * @see edu.tfh.s2.ehkbot.steuerung.BusAdressierbar#getBusAdresse()
	 */
	@Override
	public BusAdresse getBusAdresse() {
		return busAdresse;
	}

	/**
	 * Liefert den Messwert.
	 * 
	 * @return Der bearbeitete Messwert.
	 */
	public double getMesswert() {
		return steigung * getMesswertRoh() + offset;
	}

	/**
	 * Liefert den rohen Messwert.
	 * 
	 * @return Der Messwert Roh
	 */
	public double getMesswertRoh() {
		return state.getMessertRoh();
	}

	/**
	 * @see edu.tfh.s2.ehkbot.util.Subject#getState()
	 */
	public SensorState getState() {
		return state;
	}

	/**
	 * @see edu.tfh.s2.ehkbot.steuerung.BusAdressierbar#setBusAdresse(edu.tfh.s2.ehkbot.steuerung.BusAdresse)
	 */
	@Override
	public void setBusAdresse(BusAdresse busAdresse) {
		this.busAdresse = busAdresse;
	}

	/**
	 * Setzt die Koeffizienten um den MesswertRoh zu bearbeiten.
	 * 
	 * @param steigung
	 *            Der Wert wird mit MesswertRoh Mutipliziert.
	 * @param offset
	 *            Der Wert wird auf MesswertRoh addiert.
	 */
	public void setzeKoeffizienten(double steigung, double offset) {
		this.steigung = steigung;
		this.offset = offset;
	}

	/**
	 * Testet ob der Sensor funktioniert.
	 * 
	 * @return true wenn der Sensor funktioniert.
	 */
	public boolean testeFunktion() {
		return state.testeFunktion();
	}

}